
/** 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.tompai.common.bean;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;

/**
* @desc: tompai-common
* @name: DeepBeanUtils.java
* @author: tompai
* @email：liinux@qq.com
* @createTime: 2021年2月7日 下午10:53:05
* @history:
* @version: v1.0
*/

public class DeepBeanUtils {

	/**
	 * java深度克隆工具类——支持对象和对象集合
	 * @param orig  源对象
	 * @param dest  目标对象
	 */
	public static void copyProperties(final Object orig, final Object dest) {
		try {
			// DeepBeanUtils.copyProperties(dest, orig);
			org.apache.commons.beanutils.BeanUtils.copyProperties(dest, orig);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * @Description：拷贝list元素对象，将origs中的元素信息，拷贝覆盖至dests中
	 * @param origs 源list对象
	 * @param dests 目标list对象
	 * @param origsElementTpe 源list元素类型对象
	 * @param destElementTpe 目标list元素类型对象
	 * @param <T1> 源list元素类型
	 * @param <T2> 目标list元素类型
	 */
	public static <T1, T2> void copyProperties(final List<T1> origs, final List<T2> dests, Class<T1> origsElementTpe,
			Class<T2> destElementTpe) {
		if (origs == null || dests == null) {
			return;
		}
		if (dests.size() != 0) {
			// 防止目标对象被覆盖，要求必须长度为零
			throw new RuntimeException("目标对象存在值！");
		}
		try {
			for (T1 orig : origs) {
				T2 t = destElementTpe.newInstance();
				dests.add(t);
				copyProperties(orig, t);
			}
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * 大家常见的拷贝克隆的方法对于集合来说都是浅层拷贝即只是拷贝一个引用。

	诸如：Collections.addAll() 、
	Collections.copy(des,src)、
	list.clone、
	new ArrayList(list)等都是浅层拷贝，这种很容易造成数据的不安全。
	
	要安全的拷贝，深度的拷贝，要通过流-对象流。
	* @author: tompai
	* @createTime: 2021年2月7日 下午11:53:47
	* @history:
	* @param <T>
	* @param source
	* @return
	* @throws IOException
	* @throws ClassNotFoundException List<T>
	 */
	public static <T> List<T> deepCopyList(List<T> source) throws IOException, ClassNotFoundException {
		List<T> target;
		try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
				ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {
			objectOutputStream.writeObject(source);
			ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
			ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
			target = (List<T>) objectInputStream.readObject();
			return target;
		}
	}
}
